#pragma once

#include "Log.hpp"
#include "Sockets.hpp"
#include <functional>


using func_t = std::function<std::string(std::string &)>;

class TcpServer
{
public:
    TcpServer(uint16_t port, func_t callback)
        : _port(port)
        , _callback(callback)
    {}

    TcpServer()
    {}

    ~TcpServer()
    {}

public:
    bool InitServer()
    {
        _listen_socket.Socket();
        _listen_socket.Bind(_port);
        _listen_socket.Listen();
        log(Info, "init server .... done");
        return true;
    }

    void Start()
    {
        while (true)
        {
            std::string clientip;
            uint16_t clientport;
            int sockfd = _listen_socket.Accept(&clientip, &clientport);
            if(sockfd < 0)
                continue;

            if(fork() == 0)
            {
                _listen_socket.Close();
                std::string inbuffer_stream;
                while(true)
                {
                    char buffer[1024];
                    size_t n = read(sockfd, buffer, sizeof(buffer));
                    if(n > 0)
                    {
                        buffer[n] = 0;
                        inbuffer_stream += buffer;

                        while (true)
                        {
                            std::string info = _callback(inbuffer_stream);
                            if (info.empty())
                                break;
                            log(Debug, "debug, response:\n%s", info.c_str());
                            log(Debug, "debug:\n%s", inbuffer_stream.c_str());
                            write(sockfd, info.c_str(), info.size());
                        }
                    }
                    else if(n==0)
                        break;
                    else
                        break;
                }

                exit(0);
            }
            close(sockfd);
        }
        
    }

private:
    uint16_t _port;
    Sockets _listen_socket;
    func_t _callback;
};